////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2017 Qualcomm Technologies, Inc.
// All Rights Reserved.
// Confidential and Proprietary - Qualcomm Technologies, Inc.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @file  camxmultistatsoperator.h
/// @brief Define the multi statistics operator for multi camera framework.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef CAMXMULTISTATSOPERATOR_H
#define CAMXMULTISTATSOPERATOR_H

#include "camxutils.h"
#include "camxstatscommon.h"
#include "chistatsinterfacedefs.h"

CAMX_NAMESPACE_BEGIN

// Max number of properties can be used in cross-pipeline dependency
static const UINT32 MaxCrossPipelineProperties = 5;

enum class StatsAlgoSyncType
{
    StatsAlgoSyncTypeAECAWB,        ///< The Stats algorithm sync type for AEC/AWB
    StatsAlgoSyncTypeAF,            ///< The Stats algorithm sync type for AF
    StatsAlgoTypeMax                ///< The Stats algorithm sync type max
};

struct PropertyPair
{
    PropertyID          propertyIDs;                        ///< Property ID
    BOOL                isPeerDependency;                   ///< Is property dependency on peer side
};

struct MultiStatsDependency
{
    StatsAlgoSyncType   algoSyncType;                                   ///< Statistics algorithm sync type
    StatsAlgoRole       algoRole;                                       ///< Statistics algorithm role
    PropertyPair        propertyPair[MaxCrossPipelineProperties];       ///< Property dependency paris
    StatsAlgoAction     algoAction;                                     ///< Statistics algorithm action
};

struct MultiStatsData
{
    StatsAlgoSyncType   algoSyncType;                       ///< Statistics algorithm sync type
    StatsAlgoRole       algoRole;                           ///< Statistics algorithm role
    UINT                pipelineId;                         ///< Pipeline ID to which the Stats/AF node belongs
    UINT                peerPipelineId;                     ///< Pipeline ID to which the peer Stats/AF node belongs
    HwContext*          pHwContext;                         ///< Pointer to hardware context
    StatsAlgoAction     algoAction;                         ///< Statistics algorithm action
    BOOL                isSlaveOperational;                 ///< Indicate if slave has operation under LPM mode
    Node*               pNode;                              ///< Pointer to owning node
};

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Define the multi statistics operator for multi camera framework.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class MultiStatsOperator
{
public:
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// SetStatsAlgoRole
    ///
    /// @brief  Set stats algo's role
    ///
    /// @param  algoRole stats algo's role
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID SetStatsAlgoRole(
        StatsAlgoRole algoRole);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetStatsAlgoRole
    ///
    /// @brief  Get stats algo's role
    ///
    /// @return StatsAlgoRole
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    StatsAlgoRole GetStatsAlgoRole();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// Initialize
    ///
    /// @brief  Initialize the multi stats operator.
    ///
    /// @param  pMultiStatsData   Initialization data.
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual VOID Initialize(
        const MultiStatsData* pMultiStatsData) = 0;

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// UpdateStatsDependencies
    ///
    /// @brief  Get the the list of dependencies from all stats processors.
    ///
    /// @param  pStatsDependencies  Pointer to stats dependencies list
    /// @param  requestId           Request ID
    /// @param  pMultiRequestData   Multi request data
    /// @param  pIsSatisfied        Is updated dependency satisfied
    ///
    /// @return CamxResultSuccess if successful
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual CamxResult UpdateStatsDependencies(
        DependencyUnit*         pStatsDependencies,
        UINT64                  requestId,
        MultiRequestSyncData*   pMultiRequestData,
        BOOL*                   pIsSatisfied) = 0;

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetStatsAlgoAction
    ///
    /// @brief  Get statistics algo's action
    ///
    /// @return StatsAlgoAction Return stats algo's action
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual StatsAlgoAction GetStatsAlgoAction() = 0;

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// PrintDependency
    ///
    /// @brief  Print dependency information
    ///
    /// @param  pStatsDependencies Dependencies to be printed
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID PrintDependency(
        DependencyUnit*     pStatsDependencies);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// MultiStatsOperator
    ///
    /// @brief  Default Constructor
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    MultiStatsOperator() = default;

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ~MultiStatsOperator
    ///
    /// @brief  Default Destructor
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual ~MultiStatsOperator() = default;

protected:
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// AddDependency
    ///
    /// @brief  Add statistics algo's dependency
    ///
    /// @param  pPropertyPair       Pointer to statistics property pair
    /// @param  pDependencyUnit     Pointer to node's execution dependency unit
    /// @param  requestId           Request ID
    /// @param  offset              Offset to request ID
    /// @param  negative            Indicate if offset is negative
    /// @param  pIsSatisfied        If dependency is satisfied
    ///
    /// @return CamxResultSuccess   if successful
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual CamxResult AddDependency(
        PropertyPair*           pPropertyPair,
        DependencyUnit*         pDependencyUnit,
        UINT64                  requestId,
        UINT64                  offset,
        BOOL                    negative,
        BOOL*                   pIsSatisfied);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// RemoveDependency
    ///
    /// @brief  Remove statistics algo's dependency
    ///
    /// @param  pStatsDependency    Pointer to statistics dependency
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual VOID RemoveDependency(
        StatsDependency* pStatsDependency) = 0;

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// CheckIfAddDependency
    ///
    /// @brief  Check if needed to add cross pipeline dependency
    ///
    /// @param  requestId               Request ID
    /// @param  pMultiRequestData       Multi request data
    /// @param  pLPMRequestDelta        Cross pipeline request delta under LPM mode
    ///
    /// @return TRUE if needed, FALSE if not.
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual BOOL CheckIfAddDependency(
        UINT64                  requestId,
        MultiRequestSyncData*   pMultiRequestData,
        INT64*                  pLPMRequestDelta) = 0;

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ReadVendorTag
    ///
    /// @brief  Read vendor tag, and get multi camera information including:
    ///         Camera type (Wide/Tele)
    ///         Algo role (Master/Slave)
    ///         Logical camera ID
    ///
    /// @param  requestId               Request ID
    /// @param  pIsSwitched             If role switch happened
    ///
    /// @return CamxResultSuccess   if successful
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual CamxResult ReadVendorTag(
        UINT64      requestId,
        BOOL*       pIsSwitched) = 0;

    MultiStatsData              m_multiStatsData;           ///< Multi Stats Operator private data

private:
    MultiStatsOperator(const MultiStatsOperator&) = delete;                 ///< Disallow the copy constructor.
    MultiStatsOperator& operator=(const MultiStatsOperator&) = delete;      ///< Disallow assignment operator.
};

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Define the multi statistics operator for default QTI defined multi stats operator.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class QTIMultiStatsOperator final : public MultiStatsOperator
{
public:
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// Initialize
    ///
    /// @brief  Initialize the derived multi stats operator.
    ///
    /// @param  pMultiStatsData   Initialization data.
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual VOID Initialize(
        const MultiStatsData* pMultiStatsData);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// UpdateStatsDependencies
    ///
    /// @brief  Get the the list of dependencies from all stats processors for derived multi stats operator.
    ///
    /// @param  pStatsDependencies  Pointer to stats dependencies list
    /// @param  requestId           Request ID
    /// @param  pMultiRequestData   Multi request data
    /// @param  pIsSatisfied        Is updated dependency satisfied
    ///
    /// @return CamxResultSuccess if successful
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual CamxResult UpdateStatsDependencies(
        DependencyUnit*         pStatsDependencies,
        UINT64                  requestId,
        MultiRequestSyncData*   pMultiRequestData,
        BOOL*                   pIsSatisfied);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetStatsAlgoAction
    ///
    /// @brief  Get statistics algo's action
    ///
    /// @return StatsAlgoAction                 Return stats algo's action
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual StatsAlgoAction GetStatsAlgoAction();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// MultiStatsOperator
    ///
    /// @brief  Default Constructor
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    QTIMultiStatsOperator() = default;

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ~MultiStatsOperator
    ///
    /// @brief  Default Destructor
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual ~QTIMultiStatsOperator() = default;

protected:
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ReadVendorTag
    ///
    /// @brief  Read vendor tag, and get multi camera information including:
    ///         Camera type (Wide/Tele)
    ///         Algo role (Master/Slave)
    ///         Logical camera ID
    ///
    /// @param  requestId               Request ID
    /// @param  pIsSwitched             If role switch happened
    ///
    /// @return CamxResultSuccess   if successful
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual CamxResult ReadVendorTag(
        UINT64      requestId,
        BOOL*       pIsSwitched);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// CheckIfAddDependency
    ///
    /// @brief  Check if needed to add cross pipeline dependency
    ///
    /// @param  requestId               Request ID
    /// @param  pMultiRequestData       Multi request data
    /// @param  pLPMRequestDelta        Cross pipeline request delta under LPM mode
    ///
    /// @return TRUE if needed, FALSE if not.
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual BOOL CheckIfAddDependency(
        UINT64                  requestId,
        MultiRequestSyncData*   pMultiRequestData,
        INT64*                  pLPMRequestDelta);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// RemoveDependency
    ///
    /// @brief  Remove statistics algo's dependency for derived multi stats operator.
    ///
    /// @param  pStatsDependency    Pointer to statistics dependency
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual VOID RemoveDependency(
        StatsDependency* pStatsDependency);


private:
    QTIMultiStatsOperator(const QTIMultiStatsOperator&) = delete;                 ///< Disallow the copy constructor.
    QTIMultiStatsOperator& operator=(const QTIMultiStatsOperator&) = delete;      ///< Disallow assignment operator.
};

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Define the multi statistics operator for singleton algorithm intance usecase.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class SingletonStatsOperator final : public MultiStatsOperator
{
public:
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// Initialize
    ///
    /// @brief  Initialize the derived multi stats operator.
    ///
    /// @param  pMultiStatsData   Initialization data.
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual VOID Initialize(
        const MultiStatsData* pMultiStatsData);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// UpdateStatsDependencies
    ///
    /// @brief  Get the the list of dependencies from all stats processors for derived multi stats operator.
    ///
    /// @param  pStatsDependencies  Pointer to stats dependencies list
    /// @param  requestId           Request ID
    /// @param  pMultiRequestData   Multi request data
    /// @param  pIsSatisfied        Is updated dependency satisfied
    ///
    /// @return CamxResultSuccess if successful
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual CamxResult UpdateStatsDependencies(
        DependencyUnit*         pStatsDependencies,
        UINT64                  requestId,
        MultiRequestSyncData*   pMultiRequestData,
        BOOL*                   pIsSatisfied);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetStatsAlgoAction
    ///
    /// @brief  Get statistics algo's action
    ///
    /// @return StatsAlgoAction                 Return stats algo's action
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual StatsAlgoAction GetStatsAlgoAction();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// MultiStatsOperator
    ///
    /// @brief  Default Constructor
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    SingletonStatsOperator() = default;

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ~MultiStatsOperator
    ///
    /// @brief  Default Destructor
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual ~SingletonStatsOperator() = default;

protected:
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ReadVendorTag
    ///
    /// @brief  Read vendor tag, and get multi camera information including:
    ///         Camera type (Wide/Tele)
    ///         Algo role (Master/Slave)
    ///         Logical camera ID
    ///
    /// @param  requestId               Request ID
    /// @param  pIsSwitched             If role switch happened
    ///
    /// @return CamxResultSuccess   if successful
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual CamxResult ReadVendorTag(
        UINT64      requestId,
        BOOL*       pIsSwitched);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// CheckIfAddDependency
    ///
    /// @brief  Check if needed to add cross pipeline dependency
    ///
    /// @param  requestId               Request ID
    /// @param  pMultiRequestData       Multi request data
    /// @param  pLPMRequestDelta        Cross pipeline request delta under LPM mode
    ///
    /// @return TRUE if needed, FALSE if not.
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual BOOL CheckIfAddDependency(
        UINT64                  requestId,
        MultiRequestSyncData*   pMultiRequestData,
        INT64*                  pLPMRequestDelta);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// RemoveDependency
    ///
    /// @brief  Remove statistics algo's dependency for derived multi stats operator.
    ///
    /// @param  pStatsDependency    Pointer to statistics dependency
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual VOID RemoveDependency(
        StatsDependency* pStatsDependency);

private:
    SingletonStatsOperator(const SingletonStatsOperator&) = delete;                 ///< Disallow the copy constructor.
    SingletonStatsOperator& operator=(const SingletonStatsOperator&) = delete;      ///< Disallow assignment operator.
};

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Define the multi statistics operator for no 3A sync situation.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class NoSyncStatsOperator final : public MultiStatsOperator
{
public:
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// Initialize
    ///
    /// @brief  Initialize the derived multi stats operator.
    ///
    /// @param  pMultiStatsData   Initialization data.
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual VOID Initialize(
        const MultiStatsData* pMultiStatsData);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// UpdateStatsDependencies
    ///
    /// @brief  Get the the list of dependencies from all stats processors for derived multi stats operator.
    ///
    /// @param  pStatsDependencies  Pointer to stats dependencies list
    /// @param  requestId           Request ID
    /// @param  pMultiRequestData   Multi request data
    /// @param  pIsSatisfied        Is updated dependency satisfied
    ///
    /// @return CamxResultSuccess if successful
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual CamxResult UpdateStatsDependencies(
        DependencyUnit*         pStatsDependencies,
        UINT64                  requestId,
        MultiRequestSyncData*   pMultiRequestData,
        BOOL*                   pIsSatisfied);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetStatsAlgoAction
    ///
    /// @brief  Get statistics algo's action
    ///
    /// @return StatsAlgoAction                 Return stats algo's action
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual StatsAlgoAction GetStatsAlgoAction();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// MultiStatsOperator
    ///
    /// @brief  Default Constructor
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    NoSyncStatsOperator() = default;

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ~MultiStatsOperator
    ///
    /// @brief  Default Destructor
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual ~NoSyncStatsOperator() = default;

protected:
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ReadVendorTag
    ///
    /// @brief  Read vendor tag, and get multi camera information including:
    ///         Camera type (Wide/Tele)
    ///         Algo role (Master/Slave)
    ///         Logical camera ID
    ///
    /// @param  requestId               Request ID
    /// @param  pIsSwitched             If role switch happened
    ///
    /// @return CamxResultSuccess   if successful
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual CamxResult ReadVendorTag(
        UINT64      requestId,
        BOOL*       pIsSwitched);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// CheckIfAddDependency
    ///
    /// @brief  Check if needed to add cross pipeline dependency
    ///
    /// @param  requestId               Request ID
    /// @param  pMultiRequestData       Multi request data
    /// @param  pLPMRequestDelta        Cross pipeline request delta under LPM mode
    ///
    /// @return TRUE if needed, FALSE if not.
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual BOOL CheckIfAddDependency(
        UINT64                  requestId,
        MultiRequestSyncData*   pMultiRequestData,
        INT64*                  pLPMRequestDelta);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// RemoveDependency
    ///
    /// @brief  Remove statistics algo's dependency for derived multi stats operator.
    ///
    /// @param  pStatsDependency    Pointer to statistics dependency
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual VOID RemoveDependency(
        StatsDependency* pStatsDependency);

private:
    NoSyncStatsOperator(const NoSyncStatsOperator&) = delete;                 ///< Disallow the copy constructor.
    NoSyncStatsOperator& operator=(const NoSyncStatsOperator&) = delete;      ///< Disallow assignment operator.
};

CAMX_NAMESPACE_END

#endif // CAMXMULTISTATSOPERATOR_H
